1 事務特性
ACID四大特性:
-
原子性 (atomicity)
事務中的所有操作要么全部執行成功,要么會退到事務之前的狀態
-
一致性 (consistency)
一致性狀態下,所有事務對同一個數據的讀取結果是相同的
-
隔離性 (isolation)
一個事務的影響范圍在提交前對其他事務不可見(鎖機制)
-
持久性 (durability)
事務一旦提交,即可持久化到磁盤,可進行宕機恢復
2 事務實現
2.1 redo
在InnoDB存儲引擎中,事務日志通過重做日志(redo log)和日志緩沖(Log Buffer)實現,
-
開啟事務,記錄事務的序列號
-
事務執行時,往日志緩沖插入事務日志
-
事務提交,緩沖區日志寫入磁盤
-
mysql> show engine innodb status\G;
---
LOG
---
#表示當前的LSN
Log sequence number 2713307
#表示刷新到重做日志的LSN
Log flushed up to ? 2713307
Pages flushed up to 2713307
#表示刷新到磁盤的LSN
Last checkpoint at ?2713298
Max checkpoint age ? ?1736863212
Checkpoint age target 1682586237
Modified age ? ? ? ? ?0
Checkpoint age ? ? ? ?9
0 pending log flushes, 0 pending chkp writes
85 log i/o's done, 0.00 log i/o's/second注:生產環境中三個LSN的值可能是不一致的
2.2 undo
重做日志記錄了事務的行為,可以對其進行重做,但事務撤銷回滾需要用到undo。不同的是,redo存放在重做日志文件中,而undo放在數據庫內部的一個特殊段,稱為undo段,位于共享表空間中
當事務執行roll back時,會將插入的事務進行回滾,反向執行事務的操作,回滾或執行完事務后undo日志存放的表空間不會立即釋放,需等待master線程進行回收
3 事務控制
事務開啟需指定事務控制語句,或禁用自動提交
事務控制語句:
- START TRANSACTION|BEGIN:顯式地開啟一個事務
- COMMIT:提交事務
- ROLLBACK:回滾結束的事務
- SAVEPOINT identifier:允許在事務創建保存點,一個事務可以有多個point
- RELEASE SAVEPOINT identifier:刪除一個事務的保存點
- ROLLBACK TO [SAVEPOINT] identifier:與SAVEPOINT搭配使用,可以將事務回滾到標記點,不能結束事務,結束仍需執行commit或者rollback
- SET TRANSACTION:設置事務的隔離級別
在MySQL命令行下可用begin語句顯式的開啟一個事務,但在存儲過程中,只能用START TRANSACTION開啟事務
隱式提交的SQL語句
- DDL語句:數據庫、數據表操作語句
- 用戶與權限:用戶以及權限的創建刪除
- 管理語句:創建索引、分析表、優化表
3 事務的隔離級別
SQL標準定義的四種隔離級別:
-
READ UNCOMMITTED (讀未提交)
-
READ COMMITTED (RC 讀已提交)
Replication需運行在二進制日志ROW格式下,避免缺少間隙鎖導致數據同步不一致的問題
-
REPEATABLE READ (RR 可重復讀 默認)
通過Next-Key Lock鎖,避免幻讀產生
-
SERIALIZABLE (序列化)
注:上述隔離級別從低到高排列,隔離級別越低,事務請求的鎖越少
**臟讀(Drity Read):**某個事務已更新一份數據,另一個事務在此時讀取了同一份數據,由于某些原因,前一個RollBack了操作,則后一個事務所讀取的數據就會是不正確的
**不可重復讀(Non-repeatable read):**在一個事務的兩次查詢之中數據不一致,這可能是兩次查詢過程中間插入了一個事務更新的原有的數據
**幻讀(Phantom Read):**在一個事務的兩次查詢中數據筆數不一致,例如有一個事務查詢了幾列(Row)數據,而另一個事務卻在此時插入了新的幾列數據,先前的事務在接下來的查詢中,就會發現有幾列數據是它先前所沒有的
-
4 分布式事務
InnoDB支持XA事務,通過XA事務可支持分布式事務實現,分布式事務常用于銀行的轉賬系統
分布式事務由一個或多個資源管理器、事務管理器以及應用程序組成
- 資源管理器:提供訪問事務的方法
- 事務管理器:協調參與全局事務的各個事務
- 應用程序:定義事務的邊界,指定全局事務中的操作
附:
為什么企業里不使用MySQL默認的可重復讀,而使用讀已提交?
1、老版本的MySQL的binlog只支持STATEMENT格式,該格式在讀已提交下主從復制存在bug,于是MySQL默認使用可重復讀作為默認隔離級別
2、RR級別下存在間隙鎖,而RC下不存在,出現死鎖的幾率降低
3、RC級別下,半一致讀特性增加了對update操作的并發性
4、現階段RC級別的binlog支持row格式基于行的復制同步